from django.shortcuts import render
#导包
from decimal import Decimal
from meiduo_mall.utils.views import LoginRequiredJSONMixin
from django.views import View
from django.http import JsonResponse
from django_redis import get_redis_connection
from goods.models import SKU
from users.models import Address
import json
#transaction功能，开启事物
from django.db import transaction
from decimal import Decimal
from .models import OrderGoods, OrderInfo
from django.utils import timezone

# Create your views here.

# 订单结算
class OrderSettlementView(LoginRequiredJSONMixin, View):

    def get(self, request):
        # 1、提取参数
        user = request.user
        # 2、校验参数
        # 3、业务数据处理 —— 读取购物车数据和收货地址
        # 3.1、由于当前接口只允许登陆用户访问，那么购物车数据必然合并到redis了
        conn = get_redis_connection('carts')
        # redis_cart = {b'1': b'5'}
        redis_cart = conn.hgetall('carts_%s'%user.id)
        # redis_selected = [b'1']
        redis_selected = conn.smembers('selected_%s'%user.id)
        # 3.2、读取mysql商品详细信息
        sku_ids = redis_cart.keys() # [b'1']
        skus = []
        for sku_id in sku_ids:
            # 当且仅当该sku被选中，才获取详细信息，构建响应数据
            if sku_id in redis_selected:
                sku = SKU.objects.get(pk=sku_id)
                skus.append({
                    'id': sku.id,
                    'name': sku.name,
                    'default_image_url': sku.default_image.url,
                    'count': int(redis_cart[sku_id]),
                    'price': sku.price
                })

        address_queryset = Address.objects.filter(user=user)
        addresses = []
        for address in address_queryset:
            addresses.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'mobile': address.mobile,
                'receiver': address.receiver
            })

        freight = Decimal('10.00') # 保证精度
        # 4、构建响应
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'context': {
                'addresses': addresses,
                'skus': skus,
                'freight': freight # 运费
            }
        })


#提交订单－－新建订单和订单商品数据保存的数据库
class OrderCommitView(LoginRequiredJSONMixin, View):
    def post(self, request):
        #提取参数
        user = request.user
        data = json.loads(request.body.decode())
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')
        #提取购物车商品数据
        conn = get_redis_connection('carts')
        redis_carts = conn.hgetall('carts_%s' % user.id)
        redis_selected = conn.smembers('selected_%s' % user.id)
        cart_dict = {}
        for k, v in redis_carts.items():
            if k in redis_selected:
                sku_id = int(k)
                count = int(v)
                cart_dict[sku_id] = {
                    "count": count,
                    "selected": True
                }

        #校验参数
        if not all([address_id, pay_method]):
            return JsonResponse({
                'code': 400,
                'errmsg': '缺少参数'
            })
        try:
            address = Address.objects.get(pk=address_id)
        except Address.DoesNotExist as e:
            return JsonResponse({'code': 400, 'errmsg': '地址不存在'})

        if not pay_method in [OrderInfo.PAY_METHODS_ENUM['CASH'],
                              OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 400, 'errmsg': '支付方式不支持'})
        #业务数据处理－－新建订单和订单商品数据保存数据库
        cur_time = timezone.localtime()
        order_id = cur_time.strftime("%Y%m%d%H%M%S") + "%06d" % user.id

        with transaction.atomic():
            #在订单新建之前，设置一个保存点，用于回滚
            save_id = transaction.savepoint()
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count = 0,
                total_amount = 0,
                freight=Decimal('10.00'),
                pay_method = pay_method,
                status=OrderInfo.ORDER_STATUS_ENUM['UNPAID']

            )
            #新建订单商品表数据OrderGoods
            sku_ids = cart_dict.keys()
            for sku_id in sku_ids:
                while True:
                    #每遍历出一个sku_id,就需要往OrderGoods表中插入一条数据
                    sku = SKU.objects.get(pk=sku_id)
                    #获取旧库存和销量
                    old_stock = sku.stock
                    old_sales = sku.sales

                    #判断库存够不够，修改销量和库存
                    count = cart_dict[sku_id]['count']
                    if count > old_stock:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'code': 400,
                                             'errmsg': '库存不足！'})

                    #修改sku库存和销量
                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()
                    new_stock = old_stock - count
                    new_sales = old_sales + count

                    #乐观锁
                    result = SKU.objects.filter(
                        pk=sku.id, stock=old_stock, sales=old_sales
                    ).update(
                        stock=new_stock, sales=new_sales
                    )
                    if result == 0:
                        continue
                    break



                #修改spu销量
                sku.spu.sales += count
                sku.spu.save()

                #统计订单中的商品总数和订单总价格
                order.total_count += count
                order.total_amount += sku.price * count
                #新建订单商品数据，关联sku和订单
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price
                )
            order.total_amount += Decimal('10.0')
            order.save()

            #清除保存点
            transaction.savepoint_commit(save_id)

        #删除购物车选中的sku商品（买过的商品）
        sku_ids = cart_dict.keys()
        p = conn.pipeline()
        p.hdel('carts_%s' % user.id, *sku_ids)
        p.srem('selected_%s' % user.id, *sku_ids)
        p.execute()
        #构建响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'order_id': order_id})